package com.sping_boot3.spirng_boot3.juc;

import lombok.Data;
import lombok.SneakyThrows;

import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

@Data
public class Alternate_Lock {
    ReentrantLock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    private int anInt = 0;

    @SneakyThrows
    public void add() {
        lock.lock();
        try {
            while (anInt != 0) {
                condition.await();
            }
            anInt++;
            System.out.println(Thread.currentThread().getName() + ":1");
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    @SneakyThrows
    public void decr() {
        lock.lock();

        try {
            while (anInt != 1) {
                condition.await();
            }
            anInt--;
            System.out.println(Thread.currentThread().getName() + ":0");
            System.out.println("----------------------------------");
            condition.signalAll();


        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {

    }

   /* final int acquire(AbstractQueuedSynchronizer.Node node, int arg, boolean shared, boolean interruptible, boolean timed, long time) {
        Thread current = Thread.currentThread();
        byte spins = 0;
        byte postSpins = 0;
        boolean interrupted = false;
        boolean first = false;
        AbstractQueuedSynchronizer.Node pred = null;
        //无线循环
        for (; ; ) {
            //如果first不为false 且 pred不为null 且 head == pred 的布尔值赋值给first不能为false
            if (!first && (pred = (node == null) ? null : node.prev) != null && !(first = (head == pred))) {
                if (pred.status < 0) {
                    cleanQueue();           // predecessor cancelled
                    continue;
                } else if (pred.prev == null) {
                    Thread.onSpinWait();    // ensure serialization
                    continue;
                }
            }
            if (first || pred == null) {
                boolean acquired;
                try {
                    if (shared) {
                        acquired = (tryAcquireShared(arg) >= 0);
                    } else {
                        acquired = tryAcquire(arg);
                    }
                } catch (Throwable ex) {
                    cancelAcquire(node, interrupted, false);
                    throw ex;
                }
                if (acquired) {
                    if (first) {
                        node.prev = null;
                        head = node;
                        pred.next = null;
                        node.waiter = null;
                        if (shared)
                            signalNextIfShared(node);
                        if (interrupted)
                            current.interrupt();
                    }
                    return 1;
                }
            }
            if (node == null) {                 // allocate; retry before enqueue
                if (shared) {
                    node = new AbstractQueuedSynchronizer.SharedNode();
                } else {
                    node = new AbstractQueuedSynchronizer.ExclusiveNode();
                }
            } else if (pred == null) {          // try to enqueue
                node.waiter = current;
                AbstractQueuedSynchronizer.Node t = tail;
                node.setPrevRelaxed(t);         // avoid unnecessary fence
                if (t == null) {
                    tryInitializeHead();
                } else if (!casTail(t, node)) {
                    node.setPrevRelaxed(null);  // back out
                } else {
                    t.next = node;
                }
            } else if (first && spins != 0) {
                --spins;                        // reduce unfairness on rewaits
                Thread.onSpinWait();
            } else if (node.status == 0) {
                node.status = WAITING;          // enable signal and recheck
            } else {
                long nanos;
                spins = postSpins = (byte) ((postSpins << 1) | 1);
                if (!timed) {
                    LockSupport.park(this);
                } else if ((nanos = time - System.nanoTime()) > 0L) {
                    LockSupport.parkNanos(this, nanos);
                } else {
                    break;
                }
                node.clearStatus();
                if ((interrupted |= Thread.interrupted()) && interruptible) {
                    break;
                }
            }
        }
    }*/
}
